package com.gqb.util;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.gqb.annotation.Controller;

public class ClassUtil {
	/**
	 * 获取指定目录下的所有，带有
	 * @param path
	 * @param clazz
	 * @return
	 * @throws UnsupportedEncodingException 
	 * @throws ClassNotFoundException 
	 */
	public static Set<Class<?>> getClasses(String packageName,Class<? extends Annotation> clazz) throws UnsupportedEncodingException, ClassNotFoundException{
		Set<Class<?>> controllersClasses=new HashSet<>();
		String rootPath=ClassUtil.class.getResource("/").getPath();
		rootPath = URLDecoder.decode(rootPath, "utf-8");
		File packageFile=new File(rootPath+File.separator+packageName.replace(".", File.separator));
		File[] files=packageFile.listFiles();
		for (File file : files) {
			String fileName=packageName+"."+file.getName().substring(0,file.getName().length()-".class".length());
			Class<?> fileClazz=Class.forName(fileName);
			if(fileClazz.isAnnotationPresent(clazz)){
				controllersClasses.add(fileClazz);
			}
		}
		return controllersClasses;
	}
	
	/**
	 * 获取指定类 targetClass 下的，所有被annotationClass 标注的域（字段）
	 * @param targetClazz
	 * @param annotationClass
	 * @return
	 */
	public static List<Field> getFields(Class<?> targetClazz,Class<? extends Annotation> annotationClass){
		List<Field> fieldsAnnotation=new ArrayList<Field>();
		Field[] fields=targetClazz.getDeclaredFields();
		for (Field field : fields) {
			if(field.isAnnotationPresent(annotationClass)){
				fieldsAnnotation.add(field);
			}
		}
		return fieldsAnnotation;
	}
	
	/**
	 * 获取指定类targetClass 下的，被annotationClass 标注的方法
	 * @param targetClass
	 * @param annotationClass
	 * @return
	 */
	public static List<Method> getMethods(Class<?> targetClass,Class<? extends Annotation> annotationClass){
		List<Method> methodsAnn=new ArrayList<>();
		Method[] methods=targetClass.getDeclaredMethods();
		for (Method method : methods) {
			if(method.isAnnotationPresent(annotationClass)){
				methodsAnn.add(method);
			}
		}
		return methodsAnn;
	}
	/**
	 * 通过反射调用方法
	 * @param targetObject
	 * @param method
	 * @param params
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static Object invokeMethod(Object targetObject, Method method) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		method.setAccessible(true);
		return method.invoke(targetObject);
	}
}
